﻿using LightWadf.Filter;
using LightWadf.Processor;
using LightWadf.Route;
using LightWadf.Util;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Web;

namespace LightWadf.Handler
{
    public class DefaultHandler : IHttpHandler
    {
        /// <summary>
        /// 整个项目所有的路由
        /// </summary>
        private DefaultRoute route = null;
        private Assembly assembly = Assembly.Load(ConfigurationManager.AppSettings["DllName"]);

        // 过滤器集合
        private Dictionary<Attribute, IFilter> filters = new Dictionary<Attribute, IFilter>();

        public DefaultHandler()
        {
            Dictionary<string, object> dic = new Dictionary<string, object>();
            dic.Add("Name", "test");
            dic.Add("test", DateTime.Now);

            dynamic model = dic;

            this.route = new DefaultRoute();

            // 扫描所有的处理器，获取其路由
            Type[] types = this.assembly.GetTypes();
            string nameSpace = ConfigurationManager.AppSettings["ProcessorNamespace"];
            if (string.IsNullOrEmpty(nameSpace))
            {
                LogUtil.WritelnLog("未在 Web.config 中配置 ProcessorNamespace，无法对 DefaultHandler 进行初始化");
                throw new TypeInitializationException("LightWadf.Handler.DefaultHandler", 
                    new Exception("未在 Web.config 中配置 ProcessorNamespace，无法对 DefaultHandler 进行初始化"));
            }
            foreach (Type type in types)
            {
                if (type.Namespace == nameSpace)
                {
                    AbstractProcessor processor = Activator.CreateInstance(type) as AbstractProcessor;
                    if (processor != null)
                    {
                        processor.InitRouteRule();
                        this.route.MergeRoute(processor.Route);
                    }
                }
            }
        }

        public bool IsReusable
        {
            get { return true; }
        }

        public void ProcessRequest(HttpContext context)
        {
            var matchResult = this.route.Match(context.Request.Path, context.Request.HttpMethod);
            RouteTrie routeTrie = matchResult.Item1;
            if (routeTrie == null || string.IsNullOrEmpty(routeTrie.ProcessorName) || string.IsNullOrEmpty(routeTrie.MethodName))
            {
                context.Response.StatusCode = 404;
            }
            else
            {
                try
                {
                    Type processorType = this.assembly.GetType(ConfigurationManager.AppSettings["ProcessorNamespace"] + '.' + routeTrie.ProcessorName);
                    AbstractProcessor processor = Activator.CreateInstance(processorType) as AbstractProcessor;
                    if (processor == null)
                    {
                        LogUtil.WritelnLog("DefaultHandler 通过代理创建 " + routeTrie.ProcessorName + " 处理器时出错");
                        context.Response.Write("错误代码：500 请查看日志文件了解错误原因");
                    }
                    // 获取逻辑处理方法
                    MethodInfo method = processor.GetType().GetMethod(routeTrie.MethodName);

                    object result = null;
                    // 处理器的前置处理(Before Filter)
                    // 获取过滤器
                    var processorAttributes = processorType.GetCustomAttributes(typeof(IFilter));
                    result = this.DoBeforeFilter(processorAttributes, context);

                    // 逻辑处理方法的前置处理
                    // 获取逻辑处理方法的过滤器
                    var methodAttributes = method.GetCustomAttributes(typeof(IFilter));
                    if (result == null)
                    {
                        result = this.DoBeforeFilter(methodAttributes, context);
                    }

                    #region 处理器调用逻辑处理方法
                    if (result == null)
                    {
                        if (matchResult.Item2 != null && matchResult.Item2.Count != 0)
                        {
                            try
                            {
                                result = method.Invoke(processor, new object[] { context, matchResult.Item2 });
                            }
                            catch (Exception e)
                            {
                                result = method.Invoke(processor, new object[] { context });
                            }
                        }
                        else
                        {
                            result = method.Invoke(processor, new object[] { context });
                        }
                    }
                    ResultParser.Parse(result, context.Response);
                    #endregion

                    // 逻辑处理方法的后置处理
                    this.DoAfterFilter(methodAttributes, context);

                    // 处理器的后置处理(After Filter)
                    this.DoAfterFilter(processorAttributes, context);
                }
                catch (Exception e)
                {
                    LogUtil.WritelnLog(e.Message);
                    context.Response.Write("错误代码：500 请查看日志文件了解错误原因");
                }
            }
        }

        private object DoBeforeFilter(IEnumerable<Attribute> attributes, HttpContext context)
        {
            if (attributes != null)
            {
                IFilter filter = null;
                foreach (var attribute in attributes)
                {
                    if (!this.filters.ContainsKey(attribute))
                    {
                        // 如果当前不存在过滤器实例，则反射创建
                        filter = Activator.CreateInstance(attribute.GetType()) as IFilter;
                        this.filters.Add(attribute, filter);
                    }
                    else
                    {
                        filter = this.filters[attribute];
                    }
                    object result = filter.BeforeProcess(context);
                    if (result != null) return result;
                }
            }
            return null;
        }

        private void DoAfterFilter(IEnumerable<Attribute> attributes, HttpContext context)
        {
            if (attributes != null)
            {
                IFilter filter = null;
                foreach (var attribute in attributes)
                {
                    if (!this.filters.ContainsKey(attribute))
                    {
                        // 如果当前不存在过滤器实例，则反射创建
                        filter = Activator.CreateInstance(attribute.GetType()) as IFilter;
                        this.filters.Add(attribute, filter);
                    }
                    else
                    {
                        filter = this.filters[attribute];
                    }
                    filter.AfterProcess(context);
                }
            }
        }
    }
}